﻿using System;
using System.Collections.Generic;
using System.Linq;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Threading;
using unTroublemaker;

namespace unTroublemakerUI.ViewModel
{
    internal class SpecificationItemViewModel : ViewModelBase, ISpecificationItemViewModel
    {
        private readonly SpecificationItemViewModel _parent;
        private readonly ISpecificationItem _specItem;
        private RunStatus _status;
        private bool _expanded;
        private DateTime _startedAt;

        public SpecificationItemViewModel(ISpecificationItem specItem) : this(null, specItem) { }

        public SpecificationItemViewModel(SpecificationItemViewModel parent, ISpecificationItem specItem)
        {
            _parent = parent;
            _specItem = specItem;
            SubItems = _specItem.ChildItems.Select(item => new SpecificationItemViewModel(this, item)).ToArray();

            _specItem.StatusChanged += OnStatusChanged;
        }

        private void OnStatusChanged(ISpecificationItem sender, StatusChangedEventArgs args)
        {
            if (args.NewRunStatus == RunStatus.Running)
                _startedAt = DateTime.Now;
            else
                HaltIfToFast();

            UpdateStatus(args.NewRunStatus);
        }

        private void HaltIfToFast()
        {
            const int minTimeMs = 10;
            var duration = (int)DateTime.Now.Subtract(_startedAt).TotalMilliseconds;
            var timeLeft = minTimeMs - duration;
            if(timeLeft > 0)
                System.Threading.Thread.Sleep(timeLeft);
        }

        private void UpdateStatus(RunStatus status)
        {
            _status = status;
            DispatcherHelper.RunAsync(() =>
            {
                if (status == RunStatus.Failed)
                    ExpandToVisible();
                else if (status == RunStatus.Passed)
                    PassChildItems();

                RaisePropertyChanged(() => Working);
                RaisePropertyChanged(() => Passed);
                RaisePropertyChanged(() => Failed);
            });
        }

        private void PassChildItems()
        {
            foreach (var child in SubItems.OfType<SpecificationItemViewModel>())
                child.UpdateStatus(RunStatus.Passed);
        }

        private void ExpandToVisible()
        {
            Expanded = true;
            if(_parent != null)
                _parent.ExpandToVisible();
        }

        public bool Working { get { return _status == RunStatus.Running; } }
        public bool Passed { get { return _status == RunStatus.Passed; } }
        public bool Failed { get { return _status == RunStatus.Failed; } }

        public string DisplayName { get { return _specItem.DisplayName; } }
        public IEnumerable<ISpecificationItemViewModel> SubItems { get; private set; }

        public bool Expanded
        {
            get { return _expanded; }
            set { Set(() => Expanded, ref _expanded, value); }
        }
    }
}